If you write code, write docs. – Make up by myself
目录 Table of Contents
背景
作为一个轻度强迫症候群者,单纯觉得人工写文档也太让人难受了(还有点累。其次是希望自己可以养成先出文档后写代码的好习惯,所以就迫切需要一个提高生产效率的文档生成工具了。
总的来说,我们希望解决以下问题:
写文档就像填表格,固定的输入规则对应固定的输出格式
整体应用文档应有这些内容:
具体接口文档应有这些内容:
功能描述
请求方法
请求路径
请求参数(规格和示例)
响应状态
响应参数(规格和示例)
最好具备一定的接口测试功能
技术选型 编码后写 手写 markdown
文档:格式和内容容易出错,写完代码后再写文档积极性也不高,不推荐这样做。
测试时写 postman + docgen
:可以实现在线发布接口文档和离线导出接口文档。优点在于无侵入和允许可视化操作,缺点在于请求参数和响应参数无法增加规格描述。
编码前写 swaggo + swagger-markdown
:可以实现在线发布接口文档和离线导出接口文档。优点在于同时满足接口文档格式、内容和测试等方面的要求,缺点在于有侵入即需要改造原有项目。
安装工具 安装及使用 swaggo
工具:
1 2 3 4 5 6 7 8 9 10 go get github.com/swaggo/swag/cmd/swag go get -u github.com/swaggo/gin-swagger go get -u github.com/swaggo/gin-swagger/swaggerFiles swag init
安装及使用 swagger-markdown
工具:
1 2 3 4 5 npm install -g swagger-markdown swagger-markdown -i ${input_yaml} -o ${outputMarkdown}
编写文档 整体应用 main.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package mainimport ( "go-swagger-sample/router" "log" ) func main () { route := router.InitRouter() if err := route.Run(); err != nil { log.Fatalf("App crashed, err: %v" , err) } }
router/router.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package routerimport ( "github.com/gin-gonic/gin" swaggerFiles "github.com/swaggo/files" ginSwagger "github.com/swaggo/gin-swagger" "go-swagger-sample/controller" "go-swagger-sample/docs" ) func InitRouter () *gin .Engine { router := gin.Default() docs.SwaggerInfo.Schemes = []string {"http" , "https" } router.GET("/swagger/*any" , ginSwagger.WrapHandler(swaggerFiles.Handler)) userGroup := router.Group("/api/v1/users" ) { userGroup.GET("" , controller.ListUsers) userGroup.POST("" , controller.CreateUser) userGroup.GET("/:id" , controller.GetUser) } return router }
具体接口 controller/controller.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 package controllerimport ( "github.com/gin-gonic/gin" "go-swagger-sample/models" "net/http" ) func ListUsers (ctx *gin.Context) { user := &models.User{} if err := ctx.ShouldBind(&user); err != nil { ctx.JSON(http.StatusInternalServerError, err) } users := []models.User{*user} res := &models.Users{ TotalCount: 1 , Items: users, } ctx.JSON(http.StatusOK, res) } func CreateUser (ctx *gin.Context) { user := &models.User{} if err := ctx.ShouldBind(&user); err != nil { ctx.JSON(http.StatusInternalServerError, err) } ctx.JSON(http.StatusOK, user) } func GetUser (ctx *gin.Context) { user := &models.User{} if err := ctx.ShouldBindUri(&user); err != nil { ctx.JSON(http.StatusInternalServerError, err) } ctx.JSON(http.StatusOK, user) }
model/dto.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 package modelstype User struct { Id string `json:"id" form:"id" uri:"id" example:"1"` Username string `json:"username" form:"username" example:"admin"` Password string `json:"password" form:"password" example:"123456"` } type Users struct { TotalCount int `json:"totalcount" form:"totalcount" example:"0"` Items []User `json:"items" form:"items" example:""` }
接口测试 query
body
path
在线查看 访问 http://${ip}:${port}/swagger/index.html
可阅
离线导出 导出 markdown 格式 使用 swagger-markdown
工具将 swagger.yaml
转换为 docs.md
导出 PDF/Word/HTML 格式 使用 Typora
工具将 docs.md
转换为 docs.pdf/docs.docx/docs.html
附录